import { db } from '../../db/connection'
import { desc, eq } from 'drizzle-orm'
import { Conflict, NotFound, Unauthorized } from 'http-errors'
import bcrypt from 'bcryptjs'
import { Admin, AdminWithoutPassword, AdminWithPage, NewAdmin } from './admin.types'
import { admins } from '../../db/schema/admins'
import { Pages } from '../../types/commons'

export default class AdminServices {
  /**
   * 新增管理员
   * @param adminData
   */
  static async createAdmin(adminData: NewAdmin): Promise<AdminWithoutPassword> {
    if (await this.isUsernameExists(adminData.username)) {
      throw new Conflict('用户名已存在')
    }
    //加密密码
    adminData.password = await bcrypt.hash(adminData.password, 10)
    const [adminResult] = await db.insert(admins).values(adminData)
    // 返回完整的管理员信息
    return {
      id: adminResult.insertId,
      username: adminData.username,
      createdAt: new Date(),
      updatedAt: new Date(),
    }
  }

  /**
   * 根据id获取管理员信息
   * @param id
   */
  static async getAdminById(id: number): Promise<AdminWithoutPassword | null> {
    const adminResult = await db
      .select({
        id: admins.id,
        username: admins.username,
        createdAt: admins.createdAt,
        updatedAt: admins.updatedAt,
      })
      .from(admins)
      .where(eq(admins.id, id))
      .limit(1)
    return adminResult[0] || null
  }

  /**
   * 根据用户名获取管理员信息
   * @param username
   */
  static async getAdminByUsername(username: string): Promise<Admin | null> {
    const adminResult = await db.select().from(admins).where(eq(admins.username, username)).limit(1)
    return adminResult[0] || null
  }

  /**
   * 分页获取管理员列表
   * @param adminWithPage
   */
  static async getAdminPages(
    adminWithPage: AdminWithPage,
  ): Promise<Pages<AdminWithoutPassword> | null> {
    const { current, size } = adminWithPage
    const skip = (current - 1) * size
    const total = await this.getAdminCount()
    const adminList = await db
      .select({
        id: admins.id,
        username: admins.username,
        createdAt: admins.createdAt,
        updatedAt: admins.updatedAt,
      })
      .from(admins)
      .orderBy(desc(admins.createdAt))
      .limit(size)
      .offset(skip)
    return {
      total,
      current,
      size,
      data: adminList,
    }
  }

  /**
   * 更新管理员信息
   * @param id
   * @param adminData
   */
  static async updateAdmin(id: number, adminData: Partial<NewAdmin>): Promise<number | null> {
    const [admin, usernameExists] = await Promise.all([
      this.getAdminById(id),
      adminData.username ? this.isUsernameExists(adminData.username) : Promise.resolve(false),
    ])
    if (usernameExists) {
      throw new Conflict('用户名已存在')
    }
    if (!admin) {
      throw new NotFound('管理员不存在')
    }
    if (adminData.password) {
      adminData.password = await bcrypt.hash(adminData.password, 10)
    }
    await db
      .update(admins)
      .set({ ...adminData, updatedAt: new Date() })
      .where(eq(admins.id, id))
    return id
  }

  /**
   * 删除管理员
   * @param id
   */
  static async deleteAdmin(id: number): Promise<boolean> {
    const admin = await this.getAdminById(id)
    if (!admin) {
      throw new NotFound('管理员不存在')
    }
    await db.delete(admins).where(eq(admins.id, id))
    return true
  }

  /**
   * 判断用户名是否存在
   * @param username
   */
  static async isUsernameExists(username: string): Promise<boolean> {
    const adminResult = await db
      .select({ id: admins.id })
      .from(admins)
      .where(eq(admins.username, username))
      .limit(1)
    return adminResult.length > 0
  }

  static async getAdminCount() {
    return db.$count(admins)
  }
}
